library(readxl)
library(tidyverse)
-- Attaching packages --------------------------------------- tidyverse 1.2.1 --
v ggplot2 3.0.0     v purrr   0.2.5
v tibble  1.4.2     v dplyr   0.7.6
v tidyr   0.8.1     v stringr 1.3.1
v readr   1.1.1     v forcats 0.3.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::first()  masks xts::first()
x dplyr::lag()    masks stats::lag()
x dplyr::last()   masks xts::last()

Despesas por função (aqui!)

loadfonts()
No regular (non-bold, non-italic) version of Aharoni. Skipping setup for this font.
Algerian already registered with pdfFonts().
Andalus already registered with pdfFonts().
Angsana New already registered with pdfFonts().
AngsanaUPC already registered with pdfFonts().
Aparajita already registered with pdfFonts().
Arabic Typesetting already registered with pdfFonts().
Arial Black already registered with pdfFonts().
Arial already registered with pdfFonts().
Arial Narrow already registered with pdfFonts().
Arial Unicode MS already registered with pdfFonts().
Baskerville Old Face already registered with pdfFonts().
Bauhaus 93 already registered with pdfFonts().
Bell MT already registered with pdfFonts().
Berlin Sans FB already registered with pdfFonts().
No regular (non-bold, non-italic) version of Berlin Sans FB Demi. Skipping setup for this font.
Bernard MT Condensed already registered with pdfFonts().
Bodoni MT Poster Compressed already registered with pdfFonts().
Book Antiqua already registered with pdfFonts().
Bookman Old Style already registered with pdfFonts().
Bookshelf Symbol 7 already registered with pdfFonts().
Bradley Hand ITC already registered with pdfFonts().
Britannic Bold already registered with pdfFonts().
Broadway already registered with pdfFonts().
Browallia New already registered with pdfFonts().
BrowalliaUPC already registered with pdfFonts().
No regular (non-bold, non-italic) version of Brush Script MT. Skipping setup for this font.
Calibri already registered with pdfFonts().
Calibri Light already registered with pdfFonts().
Californian FB already registered with pdfFonts().
No regular (non-bold, non-italic) version of Cambria. Skipping setup for this font.
Candara already registered with pdfFonts().
Centaur already registered with pdfFonts().
Century already registered with pdfFonts().
Century Gothic already registered with pdfFonts().
Chiller already registered with pdfFonts().
Colonna MT already registered with pdfFonts().
Comic Sans MS already registered with pdfFonts().
Consolas already registered with pdfFonts().
Constantia already registered with pdfFonts().
Cooper Black already registered with pdfFonts().
Corbel already registered with pdfFonts().
Cordia New already registered with pdfFonts().
CordiaUPC already registered with pdfFonts().
Courier New already registered with pdfFonts().
DaunPenh already registered with pdfFonts().
David already registered with pdfFonts().
DFKai-SB already registered with pdfFonts().
DilleniaUPC already registered with pdfFonts().
DokChampa already registered with pdfFonts().
Ebrima already registered with pdfFonts().
Estrangelo Edessa already registered with pdfFonts().
EucrosiaUPC already registered with pdfFonts().
Euphemia already registered with pdfFonts().
FangSong already registered with pdfFonts().
Footlight MT Light already registered with pdfFonts().
Franklin Gothic Medium already registered with pdfFonts().
FrankRuehl already registered with pdfFonts().
FreesiaUPC already registered with pdfFonts().
Freestyle Script already registered with pdfFonts().
French Script MT already registered with pdfFonts().
Gabriola already registered with pdfFonts().
Garamond already registered with pdfFonts().
Gautami already registered with pdfFonts().
Georgia already registered with pdfFonts().
Gisha already registered with pdfFonts().
No regular (non-bold, non-italic) version of Harlow Solid Italic. Skipping setup for this font.
Harrington already registered with pdfFonts().
High Tower Text already registered with pdfFonts().
Impact already registered with pdfFonts().
Informal Roman already registered with pdfFonts().
IrisUPC already registered with pdfFonts().
Iskoola Pota already registered with pdfFonts().
JasmineUPC already registered with pdfFonts().
Jokerman already registered with pdfFonts().
Juice ITC already registered with pdfFonts().
KaiTi already registered with pdfFonts().
Kalinga already registered with pdfFonts().
Kartika already registered with pdfFonts().
Khmer UI already registered with pdfFonts().
KodchiangUPC already registered with pdfFonts().
Kokila already registered with pdfFonts().
Kristen ITC already registered with pdfFonts().
Kunstler Script already registered with pdfFonts().
Lao UI already registered with pdfFonts().
Latha already registered with pdfFonts().
Wide Latin already registered with pdfFonts().
Leelawadee already registered with pdfFonts().
Levenim MT already registered with pdfFonts().
LilyUPC already registered with pdfFonts().
More than one version of regular/bold/italic found for Lucida Bright. Skipping setup for this font.
No regular (non-bold, non-italic) version of Lucida Calligraphy. Skipping setup for this font.
Lucida Console already registered with pdfFonts().
More than one version of regular/bold/italic found for Lucida Fax. Skipping setup for this font.
No regular (non-bold, non-italic) version of Lucida Handwriting. Skipping setup for this font.
Lucida Sans Unicode already registered with pdfFonts().
No regular (non-bold, non-italic) version of Magneto. Skipping setup for this font.
Malgun Gothic already registered with pdfFonts().
Mangal already registered with pdfFonts().
Marlett already registered with pdfFonts().
Matura MT Script Capitals already registered with pdfFonts().
Microsoft Yi Baiti already registered with pdfFonts().
Microsoft Himalaya already registered with pdfFonts().
Microsoft JhengHei already registered with pdfFonts().
Microsoft New Tai Lue already registered with pdfFonts().
Microsoft PhagsPa already registered with pdfFonts().
Microsoft Sans Serif already registered with pdfFonts().
Microsoft Tai Le already registered with pdfFonts().
Microsoft Uighur already registered with pdfFonts().
Microsoft YaHei already registered with pdfFonts().
Miriam already registered with pdfFonts().
Miriam Fixed already registered with pdfFonts().
Mistral already registered with pdfFonts().
Modern No. 20 already registered with pdfFonts().
Mongolian Baiti already registered with pdfFonts().
Monotype Corsiva already registered with pdfFonts().
MoolBoran already registered with pdfFonts().
MS Reference Sans Serif already registered with pdfFonts().
MS Reference Specialty already registered with pdfFonts().
MV Boli already registered with pdfFonts().
Narkisim already registered with pdfFonts().
Niagara Engraved already registered with pdfFonts().
Niagara Solid already registered with pdfFonts().
Nyala already registered with pdfFonts().
Old English Text MT already registered with pdfFonts().
Onyx already registered with pdfFonts().
Palatino Linotype already registered with pdfFonts().
Papyrus already registered with pdfFonts().
Parchment already registered with pdfFonts().
Plantagenet Cherokee already registered with pdfFonts().
Playbill already registered with pdfFonts().
Poor Richard already registered with pdfFonts().
Pristina already registered with pdfFonts().
More than one version of regular/bold/italic found for Raavi. Skipping setup for this font.
Ravie already registered with pdfFonts().
Rod already registered with pdfFonts().
Sakkal Majalla already registered with pdfFonts().
Segoe Print already registered with pdfFonts().
Segoe Script already registered with pdfFonts().
Segoe UI already registered with pdfFonts().
Segoe UI Light already registered with pdfFonts().
Segoe UI Semibold already registered with pdfFonts().
Segoe UI Symbol already registered with pdfFonts().
Shonar Bangla already registered with pdfFonts().
Showcard Gothic already registered with pdfFonts().
Shruti already registered with pdfFonts().
SimHei already registered with pdfFonts().
Simplified Arabic already registered with pdfFonts().
Simplified Arabic Fixed already registered with pdfFonts().
SimSun-ExtB already registered with pdfFonts().
Snap ITC already registered with pdfFonts().
Source Sans Pro Black already registered with pdfFonts().
Source Sans Pro already registered with pdfFonts().
Source Sans Pro ExtraLight already registered with pdfFonts().
Source Sans Pro Light already registered with pdfFonts().
Source Sans Pro SemiBold already registered with pdfFonts().
Stencil already registered with pdfFonts().
Sylfaen already registered with pdfFonts().
Symbol already registered with pdfFonts().
Tahoma already registered with pdfFonts().
Tempus Sans ITC already registered with pdfFonts().
Times New Roman already registered with pdfFonts().
Traditional Arabic already registered with pdfFonts().
Trebuchet MS already registered with pdfFonts().
Tunga already registered with pdfFonts().
Utsaah already registered with pdfFonts().
Vani already registered with pdfFonts().
Verdana already registered with pdfFonts().
Vijaya already registered with pdfFonts().
Viner Hand ITC already registered with pdfFonts().
No regular (non-bold, non-italic) version of Vivaldi. Skipping setup for this font.
Vladimir Script already registered with pdfFonts().
Vrinda already registered with pdfFonts().
Webdings already registered with pdfFonts().
Wingdings already registered with pdfFonts().
Wingdings 2 already registered with pdfFonts().
Wingdings 3 already registered with pdfFonts().
library(ipeaData)
pibs <- ipeadata("BM12_PIBAC12")
[1] "NA. 01/1990 a 09/2017. Acesso em: 09/07/2018"
pibs <- pibs[MES=="12" & ANO %in% (2002:2017)]$VALVALOR
## incorpora na mão pib de 2017 que ainda não estava disponível no pacote ipeaData. Peguei do IBGE.
pibs <- c(pibs, 6559940)
for (i in 1:length(pibs)){
  sh_fun[,i+4] <- round(sh_fun[,i+4] / pibs[i], 4)
}
# passando para um formato tidy
sh_fun <- sh_fun %>%
  gather(5:20, key="Ano", value="Valor")
# funcoes para plotar os gráficos de barra
plot_funcoes <- function(funcao){
  ggplot(
      sh_fun %>% filter(Funcao_Maius==funcao & ente != "Consolidado"), 
      aes(
        fill = factor(ente, levels = rev(c("União", "Estados", "Municípios"))), 
        y = Valor, 
        x = Ano)) +
    #coord_flip() +
    geom_bar(stat = "identity", width=0.7, color = "white", size = 1) + #position = "fill"
    #geom_area(aes(group = ente),stat = "identity", position = "stack", color = "white") + #position = "fill"
    labs(
      x = NULL,
      y = NULL,
      fill = "Ente",
      title = paste("Distribuição das despesas com ", tolower(funcao), " por ente da Federação ","2002\u2013","2017", sep=""),
      subtitle = "Em percentuais do PIB."
    ) +
    scale_y_continuous(labels = scales::percent) +
    scale_fill_manual(values = tres_cores) +
    geom_text(aes(label= scales::percent(Valor)),size = 3, position = position_stack(vjust = 0.5), hjust = 0.5, family = "Source Sans Pro", color = "white") +
    tema_BSPN()
}
funcoes_de_interesse <- c("EDUCAÇÃO", "SAÚDE", "ASSISTÊNCIA SOCIAL", "SEGURANÇA PÚBLICA")
lapply(funcoes_de_interesse, plot_funcoes)
[[1]]

[[2]]

[[3]]

[[4]]

plot_funcoes("EDUCAÇÃO")

plot_funcoes("SAÚDE")

plot_funcoes("ASSISTÊNCIA SOCIAL")

plot_funcoes("SEGURANÇA PÚBLICA")

#ggplot(serie_f %>% filter(Funcao=="EDUCAÇÃO"), aes(x = Ano, y = Valor)) +
  #geom_point(aes(color=ente))+
  #geom_line(aes(group=ente))
  #geom_area(aes(fill = ente, group 

Todas as funções

Os ativos

library(plotly)

Attaching package: 㤼㸱plotly㤼㸲

The following object is masked from 㤼㸱package:ggplot2㤼㸲:

    last_plot

The following object is masked from 㤼㸱package:stats㤼㸲:

    filter

The following object is masked from 㤼㸱package:graphics㤼㸲:

    layout
# le os dados
ativo <- read.csv2("links-ativo.csv")
ativo$valor <- as.numeric(gsub("[.]", "", ativo$valor))
passivo <- read.csv2("links-passivo.csv")
passivo$valor <- as.numeric(gsub("[.]", "", passivo$valor))
# cores
mtx_tres_cores <- col2rgb(tres_cores_pasteis)
cores <- NULL
for (i in 1:dim(mtx_tres_cores)[2] ) {
  cores <- c(cores, paste("rgba(", mtx_tres_cores[1,i],", ",  mtx_tres_cores[2,i],", ",  mtx_tres_cores[3,i],", 0.7)", sep = ""))
}
tbl_cores <- data.frame("ente" = levels(ativo$ente),cores)
# funcao de plotagem
plota_sankey <- function(dados, rotulos, cor_nos){
  plot_ly(
    type = "sankey",
    orientation = "h",
    opacity = 0.6,
    width = 800,
    height = 600,
    textfont = list(
      family = "Source Sans Pro",
      color = "#444444",
      size = 12),
    
    node = list(
      label = rotulos,
      color = cor_nos, ##004a93
      pad = 10,
      thickness = 25,
      line = list(
        color = cor_nos,
        width = 0)),
    
    hoverlabel = list(
      font = list(
        family = "Source Sans Pro")),
    
    link = list(
      source = dados$src,
      target = dados$trg,
      value =  dados$valor,
      color =  dados$cores)) %>% 
  
    layout(
      title = "",
      font = list(
        family = "Source Sans Pro",
        size = 11,
        color = "#004a93"))
}
# funcao para processar os dados e chamar a função de plotagem
##### incluir argumento na função para cor dos nós!
plota_ente <- function(ente_in, dados, cor_nos){
  
  if (ente_in == "Consolidado") {
    dados_ente <- dados}
    else {dado_ente <- dados %>% filter(ente == ente_in)
  }
  
  lista_nos <- unique(c(levels(dados_ente$up), levels(dados_ente$down)))
  numeros_nos <- 0:(length(lista_nos)-1)
  nos <- data.frame(lista_nos, numeros_nos)
  
  matriz <- dados_ente %>%
    left_join(nos, by = c("up" = "lista_nos")) %>%
    rename(src = numeros_nos) %>%
    left_join(nos, by = c("down" = "lista_nos")) %>%
    rename(trg = numeros_nos)
  
  matriz <- matriz %>%
    left_join(tbl_cores)
  
  plota_sankey(matriz, lista_nos, cor_nos)
  #return(matriz)
}
#dados_consolidado <- gera_dados_ente("Consolidado")
#dados_Uniao <- gera_dados_ente("União")
#dados_Estados <- gera_dados_ente("Estados")
#dados_Municipios <- gera_dados_ente("Municípios")
plota_ente("Consolidado", ativo, "#444444")
Column `up`/`lista_nos` joining factors with different levels, coercing to character vectorColumn `down`/`lista_nos` joining factors with different levels, coercing to character vectorJoining, by = "ente"

plota_ente("Consolidado", passivo, "#333333")
Column `up`/`lista_nos` joining factors with different levels, coercing to character vectorColumn `down`/`lista_nos` joining factors with different levels, coercing to character vectorJoining, by = "ente"

Diagrama Consolidado

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KYGBge2Nzc30NCi5keWdyYXBoLWxlZ2VuZCwgLmR5Z3JhcGgtYXhpcy1sYWJlbCB7DQogIGZvbnQtZmFtaWx5OiAiU291cmNlIFNhbnMgUHJvIjsNCn0NCg0KLmR5Z3JhcGgtbGFiZWwgew0KICBmb250LWZhbWlseTogIlNvdXJjZSBTYW5zIFBybyI7DQp9DQpgYGANCg0KDQpgYGB7cn0NCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpgYGANCiMjIERlc3Blc2FzIHBvciBmdW7Dp8OjbyAoYXF1aSEpDQoNCmBgYHtyIGZ1bmNhb30NCiNsaWJyYXJ5KGV4dHJhZm9udCkNCiNmb250X2ltcG9ydCgpDQojbG9hZGZvbnRzKCkNCg0KdHJlc19jb3JlcyA8LWMoIiNGOEFDMDgiLCIjMDI4MDYzIiwiIzFFNDY2QSIpDQp0cmVzX2NvcmVzX3Bhc3RlaXMgPC0gYygiI0ZFQ0U2MCIsIiM2M0JFQUYiLCAiIzdBOUNCRCIpDQoNCnRlbWFfQlNQTiA8LSBmdW5jdGlvbigpew0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgdGhlbWUoDQogICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJTb3VyY2UgU2FucyBQcm8iLCBjb2xvdXIgPSAiZ3JleTIwIiksDQogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIlNvdXJjZSBTYW5zIFBybyIsIGNvbG91ciA9ICJncmV5MjAiKSwNCiAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiksDQogICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCANCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpDQp9DQoNCmRlc3BfZnVuIDwtIHJlYWRfZXhjZWwoImZ1bmNhb18yMDE3Lnhsc3giKQ0KDQp0YWJlbGFfbm9tZXNfZnVuY29lcyA8LSBkZXNwX2Z1blsxOjI4LDE6Ml0NCg0KZGVzcF9mdW4kcGN0VTIwMTcgPC0gMTAwKmRlc3BfZnVuJGBVTknDg09fMjAxN2AgLyByb3dTdW1zKGRlc3BfZnVuWyxjKDMsNSw3KV0pDQpkZXNwX2Z1biRwY3RVMjAxNiA8LSAxMDAqZGVzcF9mdW4kYFVOScODT18yMDE2YCAvIHJvd1N1bXMoZGVzcF9mdW5bLGMoNCw2LDgpXSkNCg0KZGVzcF9mdW4gPC0gZGVzcF9mdW5bLGMoMSwyLDksMTAsMzo4KV0NCg0KZF9mdW4gPC0gZGVzcF9mdW5bYygxOjI4LDMxKSxdICU+JQ0KICBnYXRoZXIoLTE6LTQsIGtleT0iRW50ZV9Bbm8iLCB2YWx1ZT0idmFsb3IiKSAlPiUNCiAgc2VwYXJhdGUoRW50ZV9Bbm8sIGludG8gPSBjKCJFbnRlIiwgIkFubyIpKSAjIHBvciBwYWRyw6NvIGVsZSBzZXBhcmEgcG9yIHFxIGNhcmFjdGVyZSBuw6NvLWFsZmFudW3DqXJpY28sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgb3Ugc2UgdXNhcmlhIHVtIHssc2VwID0gIl8ifQ0KDQojIHVtYSB0YWJlbGluaGEgY29tIHRvdGFpcyBlIHVtYSB2ZXJzw6NvIGRvIGRhdGFmcmFtZSBjb20gZXNzZXMgdG90YWlzIHBhcmEgb3JkZW5hciBvIGdyw6FmaWNvIGRlIHZscnMgYWJzb2x1dG9zDQoNCnRvdF9mdW5fMjAxNyA8LSBkX2Z1biAlPiUNCiAgZ3JvdXBfYnkoRnVuY2FvLCBBbm8pICU+JQ0KICBzdW1tYXJpc2Uoc29tYV9mdW5jYW8gPSBzdW0odmFsb3IpKQ0KDQpkX2Z1bl90b3QgPC0gZF9mdW4gJT4lDQogIGxlZnRfam9pbih0b3RfZnVuXzIwMTcpDQoNCiMgdW1hIG91dHJhIHRhYmVsaW5oYSBwYXJhIGNvbXBhcmFyIHByZXZpZGVuY2lhIGUgZW5jYXJnb3MgZXNwZWNpYWlzIGNvbSBhcyBkZW1haXMgZnVuY29lcw0KDQpkX2Z1bl9kZW1haXMgPC0gZF9mdW4gJT4lDQogIGZpbHRlcihBbm89PSIyMDE3IiAmICFpcy5uYShGdW5jYW8pICYgIShGdW5jYW8gJWluJSBjKCIyOCAtIEVuY2FyZ29zIEVzcGVjaWFpcyIsICIwOSAtIFByZXZpZMOqbmNpYSBTb2NpYWwiKSkpICU+JQ0KICBncm91cF9ieShFbnRlLEFubykgJT4lDQogIHN1bW1hcmlzZSh2YWxvciA9IHN1bSh2YWxvcikpICU+JQ0KICBtdXRhdGUoRnVuY2FvID0gIkRlbWFpcyBmdW7Dp8O1ZXMiKQ0KDQpkX2Z1bl9wcmV2RW5jIDwtIGRfZnVuICU+JSANCiAgZmlsdGVyKEFubz09IjIwMTciICYgIWlzLm5hKEZ1bmNhbykgJiAoRnVuY2FvICVpbiUgYygiMjggLSBFbmNhcmdvcyBFc3BlY2lhaXMiLCAiMDkgLSBQcmV2aWTDqm5jaWEgU29jaWFsIikpKSAlPiUNCiAgc2VsZWN0KEVudGUsIEFubywgdmFsb3IsIEZ1bmNhbykNCg0KZF9mdW5fcHJpbmNpcGFpcyA8LSBkX2Z1bl9wcmV2RW5jICU+JQ0KICBiaW5kX3Jvd3MoZF9mdW5fZGVtYWlzKSAlPiUNCiAgbXV0YXRlIChGdW5jYW8gPSBmYWN0b3IoRnVuY2FvKSkNCg0KIyBvcyBncsOhZmljb3MNCg0KcGxvdF9mdW5fZGFyayA8LSBnZ3Bsb3QoZF9mdW4gJT4lIGZpbHRlcihBbm89PSIyMDE3IiAmICFpcy5uYShGdW5jYW8pKSwgYWVzKGZpbGw9RW50ZSwgeT12YWxvciwgeD1GdW5jYW8pKSArDQogICAgY29vcmRfZmxpcCgpICsNCiAgICBnZW9tX2Jhciggc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbj0iZmlsbCIsIHdpZHRoPTAuNiwgY29sb3IgPSAiZ3JleTIwIiwgc2l6ZSA9IDEpICsNCiAgICBsYWJzKA0KICAgICAgeCA9IE5VTEwsDQogICAgICB5ID0gTlVMTCwNCiAgICAgIGZpbGwgPSAiRW50ZSIsDQogICAgICB0aXRsZSA9ICJEaXN0cmlidWnDp8OjbyBkYXMgZGVzcGVzYXMgcG9yIGVudGUgZGEgRmVkZXJhw6fDo28iLA0KICAgICAgc3VidGl0bGUgPSAiQ29uZm9ybWUgYSBjbGFzc2lmaWNhw6fDo28gZnVuY2lvbmFsIg0KICAgICkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsNCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjOEQ5OTNEIiwiIzQwNkFGRiIsIiNGRkQ1MDAiKSkgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgdGhlbWUoDQogICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJncmV5MjAiKSwNCiAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIlNvdXJjZSBTYW5zIFBybyIsIGNvbG91ciA9ICJ3aGl0ZSIpLA0KICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJTb3VyY2UgU2FucyBQcm8iLCBjb2xvdXIgPSAid2hpdGUiKSwNCiAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gInBsYWluIiksDQogICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCANCiAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksDQogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLA0KICAgICAgbGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpDQoNCiMgZmN0X3Jlb3JkZXIgbXVpdG8gw7p0aWwhIHPDsyBxdWUgdGVuaG8gcSBjb2xvY2FyIGVtIG9yZGVtIGRlc2NlbmRlbnRlIGRlIFBFUkNFTlRVQUwsIGUgbsOjbyBkZSB2YWxvci4gcHJlY2lzbw0KIyBjcmlhciBlc3NhIHZhcmnDoXZlbC4NCg0KcGxvdF9mdW4gPC0gZ2dwbG90KA0KICAgICAgZF9mdW4gJT4lIGZpbHRlcihBbm89PSIyMDE3IiAmICFpcy5uYShGdW5jYW8pKSwgDQogICAgICBhZXMoDQogICAgICAgIGZpbGwgPSBmYWN0b3IoRW50ZSwgbGV2ZWxzID0gcmV2KGMoIlVOScODTyIsICJFU1RBRE9TIiwgIk1VTklDw41QSU9TIikpKSwgDQogICAgICAgIHkgPSB2YWxvciwgDQogICAgICAgIHggPSBmY3RfcmVvcmRlcihGdW5jYW8scGN0VTIwMTcsZGVzYz1UUlVFKSkpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGdlb21fYmFyKCBzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uPSJmaWxsIiwgd2lkdGg9MC42LCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAxKSArDQogICAgbGFicygNCiAgICAgIHggPSBOVUxMLA0KICAgICAgeSA9IE5VTEwsDQogICAgICBmaWxsID0gIkVudGUiLA0KICAgICAgdGl0bGUgPSBwYXN0ZSgiRGlzdHJpYnVpw6fDo28gZGFzIGRlc3Blc2FzIHBvciBlbnRlIGRhIEZlZGVyYcOnw6NvICIsIlx1MjAxMyIsIiAyMDE3IiksDQogICAgICBzdWJ0aXRsZSA9ICJDb25mb3JtZSBhIENsYXNzaWZpY2HDp8OjbyBGdW5jaW9uYWwuIFBvciBvcmRlbSBkZWNyZXNjZW50ZSBkYSBwYXJ0aWNpcGHDp8OjbyBkYSBVbmnDo28gbm8gdG90YWwgZGEgZGVzcGVzYS4iDQogICAgKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKw0KICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHRyZXNfY29yZXMpICsNCiAgICB0ZW1hX0JTUE4oKQ0KDQojcmVhaXMgPC0gc2NhbGVzOjpkb2xsYXJfZm9ybWF0KHByZWZpeCA9ICJSJCAiLCBzdWZmaXggPSAiIGJpbGjDtWVzIiwgbGFyZ2VzdF93aXRoX2NlbnRzID0gMTAwMCwgYmlnLm1hcms9Ii4iLCBkZWNpbWFsLm1hcms9IiwiKQ0KI3JlYWlzKDEwMDAwKQ0KDQpwbG90X2Z1bl9hYnMgPC0gZ2dwbG90KA0KICAgICAgZF9mdW5fdG90ICU+JSBmaWx0ZXIoQW5vPT0iMjAxNyIgJiAhaXMubmEoRnVuY2FvKSAmICEoRnVuY2FvICVpbiUgYygiMjggLSBFbmNhcmdvcyBFc3BlY2lhaXMiLCAiMDkgLSBQcmV2aWTDqm5jaWEgU29jaWFsIikpKSwgDQogICAgICBhZXMoDQogICAgICAgIGZpbGwgPSBmYWN0b3IoRW50ZSwgbGV2ZWxzID0gcmV2KGMoIlVOScODTyIsICJFU1RBRE9TIiwgIk1VTklDw41QSU9TIikpKSwgDQogICAgICAgIHkgPSB2YWxvci8xMDAwLCANCiAgICAgICAgeCA9IGZjdF9yZW9yZGVyKEZ1bmNhbyxzb21hX2Z1bmNhbyxkZXNjPVRSVUUpKSkgKw0KICAgIGNvb3JkX2ZsaXAoKSArDQogICAgZ2VvbV9iYXIoIHN0YXQ9ImlkZW50aXR5Iiwgd2lkdGg9MC42LCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAxKSArDQogICAgbGFicygNCiAgICAgIHggPSBOVUxMLA0KICAgICAgeSA9IE5VTEwsDQogICAgICBmaWxsID0gIkVudGUiLA0KICAgICAgdGl0bGUgPSBwYXN0ZSgiRGVzcGVzYXMgdG90YWlzIHBvciBGdW7Dp8OjbyAiLCJcdTIwMTMiLCIgMjAxNyIpLA0KICAgICAgc3VidGl0bGUgPSAiRW0gYmlsaMO1ZXMgZGUgcmVhaXMuIEV4Y2V0byBmdW7Dp8O1ZXMgXCIyOCAtIEVuY2FyZ29zIEVzcGVjaWFpc1wiIGUgXCIwOSAtIFByZXZpZMOqbmNpYSBTb2NpYWxcIi4iDQogICAgKSArDQogICAgI3NjYWxlX3lfZGlzY3JldGUoYnJlYWtzID0gYygwLDEwMCwyMDAsMzAwKSwgbGFiZWxzID0gYygiMCIsIjEwMCIsIjIwMCIsIjMwMCIpKSArDQogICAgI3NjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsbWF4KHN1YnNldChkX2Z1bl90b3QsIGRfZnVuX3RvdCRBbm8gPT0gIjIwMTciKSRzb21hX2Z1bmNhbykvMTAwMCkpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoKSArICN1ZXhwYW5kID0gYygwLDApIHBhcmEgemVyYXIgbyBwYWRkaW5nIGVudHJlIG8gZXhpdG8gZSBvIGluw61jaW8gZG8gZ3LDoWZpY28gDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gdHJlc19jb3JlcykgKw0KICAgIHRlbWFfQlNQTigpDQoNCmZvcm1hdGFfQlIgPC0gc2NhbGVzOjpmb3JtYXRfZm9ybWF0KGJpZy5tYXJrID0gIi4iLCBkZWNpbWFsLm1hcmsgPSAiLCIsIHNjaWVudGlmaWMgPSBGQUxTRSkNCg0KcGxvdF9mdW5fYWJzX3ByaW5jaXBhaXMgPC0gZ2dwbG90KA0KICAgICAgZF9mdW5fcHJpbmNpcGFpcywgDQogICAgICBhZXMoDQogICAgICAgIGZpbGwgPSBmYWN0b3IoRW50ZSwgbGV2ZWxzID0gcmV2KGMoIlVOScODTyIsICJFU1RBRE9TIiwgIk1VTklDw41QSU9TIikpKSwgDQogICAgICAgIHkgPSB2YWxvci8xMDAwLCANCiAgICAgICAgeCA9IGZjdF9yZXYoRnVuY2FvKSkpICsNCiAgICBjb29yZF9mbGlwKCkgKw0KICAgIGdlb21fYmFyKCBzdGF0PSJpZGVudGl0eSIsIHdpZHRoPTAuNiwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMSkgKw0KICAgIGxhYnMoDQogICAgICB4ID0gTlVMTCwNCiAgICAgIHkgPSBOVUxMLA0KICAgICAgZmlsbCA9ICJFbnRlIiwNCiAgICAgIHRpdGxlID0gcGFzdGUoIkRlc3Blc2FzIHRvdGFpcyBwb3IgRnVuw6fDo28gIiwiXHUyMDEzIiwiIDIwMTciKSwNCiAgICAgIHN1YnRpdGxlID0gIkVtIGJpbGjDtWVzIGRlIHJlYWlzLiINCiAgICApICsNCiAgICAjc2NhbGVfeV9kaXNjcmV0ZShicmVha3MgPSBjKDAsMTAwLDIwMCwzMDApLCBsYWJlbHMgPSBjKCIwIiwiMTAwIiwiMjAwIiwiMzAwIikpICsNCiAgICAjc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCxtYXgoc3Vic2V0KGRfZnVuX3RvdCwgZF9mdW5fdG90JEFubyA9PSAiMjAxNyIpJHNvbWFfZnVuY2FvKS8xMDAwKSkgKw0KICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBmb3JtYXRhX0JSKSArICN1ZXhwYW5kID0gYygwLDApIHBhcmEgemVyYXIgbyBwYWRkaW5nIGVudHJlIG8gZXhpdG8gZSBvIGluw61jaW8gZG8gZ3LDoWZpY28gDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gdHJlc19jb3JlcykgKw0KICAgIHRlbWFfQlNQTigpDQoNCnBsb3RfZnVuDQpwbG90X2Z1bl9hYnNfcHJpbmNpcGFpcw0KcGxvdF9mdW5fYWJzDQoNCg0KDQoNCmBgYA0KDQpgYGB7ciBzZXJpZS1oaXN0b3JpY2EtZnVuY2FvfQ0KDQpmdW5fbXVuIDwtIHJlYWRfZXhjZWwoImNvbnNvbF9zZXJpZS54bHMiLCBzaGVldD0iRnVuY2FvIE11bmljaXBpb3MiLHNraXA9MTEsdHJpbV93cz1GQUxTRSkNCmZ1bl9lc3QgPC0gcmVhZF9leGNlbCgiY29uc29sX3NlcmllLnhscyIsIHNoZWV0PSJGdW5jYW8gRXN0YWRvcyIsc2tpcD0xMSx0cmltX3dzPUZBTFNFKQ0KZnVuX3VuaSA8LSByZWFkX2V4Y2VsKCJjb25zb2xfc2VyaWUueGxzIiwgc2hlZXQ9IkZ1bmNhbyBVbmlhbyIsc2tpcD0xMSx0cmltX3dzPUZBTFNFKQ0KZnVuX2NvbiA8LSByZWFkX2V4Y2VsKCJjb25zb2xfc2VyaWUueGxzIiwgc2hlZXQ9IkZ1bmNhbyBDb25zb2xpZGFkbyIsc2tpcD0xMSx0cmltX3dzPUZBTFNFKQ0KDQpmdW5fbXVuMiA8LSByZWFkX2V4Y2VsKCJjb21wbGVtZW50b19zZXJpZV9mdW5jb2VzXzIwMTNfMjAxNy54bHN4Iiwgc2hlZXQ9IkZ1bsOnw6NvIE11bmljw61waW9zIiwgdHJpbV93cz1GQUxTRSkNCmZ1bl9lc3QyIDwtIHJlYWRfZXhjZWwoImNvbXBsZW1lbnRvX3NlcmllX2Z1bmNvZXNfMjAxM18yMDE3Lnhsc3giLCBzaGVldD0iRnVuw6fDo28gRXN0YWRvcyIsIHRyaW1fd3M9RkFMU0UpDQpmdW5fdW5pMiA8LSByZWFkX2V4Y2VsKCJjb21wbGVtZW50b19zZXJpZV9mdW5jb2VzXzIwMTNfMjAxNy54bHN4Iiwgc2hlZXQ9IkZ1bsOnw6NvIFVuacOjbyIsIHRyaW1fd3M9RkFMU0UpDQpmdW5fY29uMiA8LSByZWFkX2V4Y2VsKCJjb21wbGVtZW50b19zZXJpZV9mdW5jb2VzXzIwMTNfMjAxNy54bHN4Iiwgc2hlZXQ9IkZ1bsOnw6NvIENvbnNvbGlkYWRvIiwgdHJpbV93cz1GQUxTRSkNCg0KdGFiZWxhX25vbWVzX2Z1bmNvZXMkRnVuY2FvX01haXVzIDwtIHRvdXBwZXIodGFiZWxhX25vbWVzX2Z1bmNvZXMkTm9tZV9mdW5jYW8pDQoNCiMgbyB0ZXN0ZS4uLg0KIyANCiMgc2hfZnVuX2NvbiA8LSBmdW5fY29uICU+JQ0KIyAgIGlubmVyX2pvaW4odGFiZWxhX25vbWVzX2Z1bmNvZXMsIGJ5ID0gYygiRlVOw4fDg08vU1VCRlVOw4fDg08iID0gIkZ1bmNhb19NYWl1cyIpKSAlPiUNCiMgICByZW5hbWUoRnVuY2FvX01haXVzID0gYEZVTsOHw4NPL1NVQkZVTsOHw4NPYCkgJT4lDQojICAgbXV0YXRlX2F0KDI6MTQsIGZ1bnMoLi8xMDAwMDAwKSkgJT4lICN3b3chDQojICAgc2VsZWN0KDE1LDE2LDEsMjoxNCkgJT4lDQojICAgbGVmdF9qb2luKGZ1bl9jb24yLCBieSA9IGMoIkZ1bmNhbyIgPSAiWF9fMSIpKQ0KDQojIHVtYSBmdW7Dp8OjbyBwYXJhIHByb2Nlc3NhciBlc3NlcyBhcnF1aXZvcyBlIGp1bnTDoS1sb3MuIG9saGEgcXVlIGNvaXNhIGxpbmRhLg0KDQpnZXJhX3NoIDwtIGZ1bmN0aW9uKHNoMSwgc2gyKXsNCiAgc2gxICU+JQ0KICAgIGlubmVyX2pvaW4odGFiZWxhX25vbWVzX2Z1bmNvZXMsIGJ5ID0gYygiRlVOw4fDg08vU1VCRlVOw4fDg08iID0gIkZ1bmNhb19NYWl1cyIpKSAlPiUNCiAgICByZW5hbWUoRnVuY2FvX01haXVzID0gYEZVTsOHw4NPL1NVQkZVTsOHw4NPYCkgJT4lDQogICAgbXV0YXRlX2F0KDI6MTQsIGZ1bnMoLi8xMDAwMDAwKSkgJT4lICN3b3chIHBxIGFzIHByaW1laXJhcyB0YWJlbGFzIGVzdMOjbyBlbSBSJCwgYXMgc2VndW5kYXMgZW0gbWlsaMO1ZXMNCiAgICBzZWxlY3QoMTUsMTYsMSw0OjE0KSAlPiUgIyBkZXNwcmV6YW5kbyBvcyBhbm9zIGRlIDIwMDAgZSAyMDAxIChjb2x1bmFzIDIgZSAzKSwgcG9yIGVzdGFyZW0gaW5jb21wbGV0b3MuDQogICAgbGVmdF9qb2luKHNoMiwgYnkgPSBjKCJGdW5jYW8iID0gIlhfXzEiKSkgICAgDQp9DQoNCnNoX2Z1bl9jb24gPC0gZ2VyYV9zaChmdW5fY29uLCBmdW5fY29uMikNCnNoX2Z1bl9tdW4gPC0gZ2VyYV9zaChmdW5fbXVuLCBmdW5fbXVuMikNCnNoX2Z1bl9lc3QgPC0gZ2VyYV9zaChmdW5fZXN0LCBmdW5fZXN0MikNCnNoX2Z1bl91bmkgPC0gZ2VyYV9zaChmdW5fdW5pLCBmdW5fdW5pMikNCg0KIyBhY3Jlc2NlbnRhciBvICJlbnRlIiBlbSBjYWRhIHRhYmVsYSBlIGp1bnRhciB0dWRvDQoNCmxpc3RhX2RmcyA8LSBsaXN0KHNoX2Z1bl9jb24sIHNoX2Z1bl9tdW4sIHNoX2Z1bl9lc3QsIHNoX2Z1bl91bmkpDQplbnRlcyA8LSBjKCJDb25zb2xpZGFkbyIsICJNdW5pY8OtcGlvcyIsICJFc3RhZG9zIiwgIlVuacOjbyIpDQoNCmZvciAoaSBpbiAxOjQpew0KICBsaXN0YV9kZnNbW2ldXSRlbnRlIDwtIGVudGVzW2ldDQp9DQoNCnNoX2Z1biA8LSBiaW5kX3Jvd3MobGlzdGFfZGZzKQ0Kc2hfZnVuIDwtIHNoX2Z1blssYygxOjMsMjAsNDoxOSldDQoNCiMgY8OzZGlnbyBhbnRpZ28NCiMNCiMgbXVuIDwtIGZ1bl9tdW5bd2hpY2goZnVuX211biRgRlVOw4fDg08vU1VCRlVOw4fDg09gICVpbiUgZnVuY29lc19kZV9pbnRlcmVzc2UpLF0NCiMgbXVuJGVudGUgPC0gIk11bmljw61waW9zIg0KIyANCiMgZXN0IDwtIGZ1bl9lc3Rbd2hpY2goZnVuX2VzdCRgRlVOw4fDg08vU1VCRlVOw4fDg09gICVpbiUgZnVuY29lc19kZV9pbnRlcmVzc2UpLF0NCiMgZXN0JGVudGUgPC0gIkVzdGFkb3MiDQojIA0KIyB1bmkgPC0gZnVuX3VuaVt3aGljaChmdW5fdW5pJGBGVU7Dh8ODTy9TVUJGVU7Dh8ODT2AgJWluJSBmdW5jb2VzX2RlX2ludGVyZXNzZSksXQ0KIyB1bmkkZW50ZSA8LSAiVW5pw6NvIg0KIyANCiMgc2VyaWVfZnVuY29lcyA8LSByYmluZChtdW4sZXN0LHVuaSlbLC0yOi0zXQ0KDQojIG5vcm1hbGl6YXIgcGVsbyBwaWIgYWdvcmENCg0KIyMgaW1wb3J0YSBwaWIgZG8gSXBlYURhdGENCg0KbGlicmFyeShpcGVhRGF0YSkNCnBpYnMgPC0gaXBlYWRhdGEoIkJNMTJfUElCQUMxMiIpDQpwaWJzIDwtIHBpYnNbTUVTPT0iMTIiICYgQU5PICVpbiUgKDIwMDI6MjAxNyldJFZBTFZBTE9SDQoNCiMjIGluY29ycG9yYSBuYSBtw6NvIHBpYiBkZSAyMDE3IHF1ZSBhaW5kYSBuw6NvIGVzdGF2YSBkaXNwb27DrXZlbCBubyBwYWNvdGUgaXBlYURhdGEuIFBlZ3VlaSBkbyBJQkdFLg0KDQpwaWJzIDwtIGMocGlicywgNjU1OTk0MCkNCg0KZm9yIChpIGluIDE6bGVuZ3RoKHBpYnMpKXsNCiAgc2hfZnVuWyxpKzRdIDwtIHJvdW5kKHNoX2Z1blssaSs0XSAvIHBpYnNbaV0sIDQpDQp9DQoNCiMgcGFzc2FuZG8gcGFyYSB1bSBmb3JtYXRvIHRpZHkNCg0Kc2hfZnVuIDwtIHNoX2Z1biAlPiUNCiAgZ2F0aGVyKDU6MjAsIGtleT0iQW5vIiwgdmFsdWU9IlZhbG9yIikNCg0KDQojIGZ1bmNvZXMgcGFyYSBwbG90YXIgb3MgZ3LDoWZpY29zIGRlIGJhcnJhDQoNCnBsb3RfZnVuY29lcyA8LSBmdW5jdGlvbihmdW5jYW8pew0KICBnZ3Bsb3QoDQogICAgICBzaF9mdW4gJT4lIGZpbHRlcihGdW5jYW9fTWFpdXM9PWZ1bmNhbyAmIGVudGUgIT0gIkNvbnNvbGlkYWRvIiksIA0KICAgICAgYWVzKA0KICAgICAgICBmaWxsID0gZmFjdG9yKGVudGUsIGxldmVscyA9IHJldihjKCJVbmnDo28iLCAiRXN0YWRvcyIsICJNdW5pY8OtcGlvcyIpKSksIA0KICAgICAgICB5ID0gVmFsb3IsIA0KICAgICAgICB4ID0gQW5vKSkgKw0KICAgICNjb29yZF9mbGlwKCkgKw0KICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aD0wLjcsIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDEpICsgI3Bvc2l0aW9uID0gImZpbGwiDQogICAgI2dlb21fYXJlYShhZXMoZ3JvdXAgPSBlbnRlKSxzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAic3RhY2siLCBjb2xvciA9ICJ3aGl0ZSIpICsgI3Bvc2l0aW9uID0gImZpbGwiDQogICAgbGFicygNCiAgICAgIHggPSBOVUxMLA0KICAgICAgeSA9IE5VTEwsDQogICAgICBmaWxsID0gIkVudGUiLA0KICAgICAgdGl0bGUgPSBwYXN0ZSgiRGlzdHJpYnVpw6fDo28gZGFzIGRlc3Blc2FzIGNvbSAiLCB0b2xvd2VyKGZ1bmNhbyksICIgcG9yIGVudGUgZGEgRmVkZXJhw6fDo28gIiwiMjAwMlx1MjAxMyIsIjIwMTciLCBzZXA9IiIpLA0KICAgICAgc3VidGl0bGUgPSAiRW0gcGVyY2VudHVhaXMgZG8gUElCLiINCiAgICApICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArDQogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gdHJlc19jb3JlcykgKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWw9IHNjYWxlczo6cGVyY2VudChWYWxvcikpLHNpemUgPSAzLCBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwgaGp1c3QgPSAwLjUsIGZhbWlseSA9ICJTb3VyY2UgU2FucyBQcm8iLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgICB0ZW1hX0JTUE4oKQ0KfQ0KDQpmdW5jb2VzX2RlX2ludGVyZXNzZSA8LSBjKCJFRFVDQcOHw4NPIiwgIlNBw5pERSIsICJBU1NJU1TDik5DSUEgU09DSUFMIiwgIlNFR1VSQU7Dh0EgUMOaQkxJQ0EiKQ0KDQpsYXBwbHkoZnVuY29lc19kZV9pbnRlcmVzc2UsIHBsb3RfZnVuY29lcykNCg0KIyBwbG90X2Z1bmNvZXMoIkVEVUNBw4fDg08iKQ0KIyBwbG90X2Z1bmNvZXMoIlNBw5pERSIpDQojIHBsb3RfZnVuY29lcygiQVNTSVNUw4pOQ0lBIFNPQ0lBTCIpDQojIHBsb3RfZnVuY29lcygiU0VHVVJBTsOHQSBQw5pCTElDQSIpDQoNCiNnZ3Bsb3Qoc2VyaWVfZiAlPiUgZmlsdGVyKEZ1bmNhbz09IkVEVUNBw4fDg08iKSwgYWVzKHggPSBBbm8sIHkgPSBWYWxvcikpICsNCiAgI2dlb21fcG9pbnQoYWVzKGNvbG9yPWVudGUpKSsNCiAgI2dlb21fbGluZShhZXMoZ3JvdXA9ZW50ZSkpDQogICNnZW9tX2FyZWEoYWVzKGZpbGwgPSBlbnRlLCBncm91cCA9IGVudGUpLCBzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb249InN0YWNrIikNCg0KYGBgDQojIyBUb2RhcyBhcyBmdW7Dp8O1ZXMNCg0KYGBge3J9DQp0YWJlbGFfc2ggPC0gc2hfZnVuICU+JSANCiAgZmlsdGVyKGVudGUgPT0gIkNvbnNvbGlkYWRvIikgJT4lDQogIHNlbGVjdCgxLDUsNikgJT4lDQogIHNwcmVhZChrZXkgPSAiQW5vIiwgdmFsdWUgPSAiVmFsb3IiKQ0KDQp3cml0ZS5jc3YyKHRhYmVsYV9zaCwgZmlsZT0idGFiZWxhX3NoLmNzdiIpDQoNCnNoX2xpbmhhcyA8LSBzaF9mdW4gJT4lIA0KICBmaWx0ZXIoZW50ZSA9PSAiQ29uc29saWRhZG8iICYgIShGdW5jYW8gJWluJSBjKCIyOCAtIEVuY2FyZ29zIEVzcGVjaWFpcyIsICIwOSAtIFByZXZpZMOqbmNpYSBTb2NpYWwiKSkpICU+JQ0KICBtdXRhdGUoVmFsb3IgPSBWYWxvcioxMDApDQoNCmxpYnJhcnkoaGlnaGNoYXJ0ZXIpDQoNCmhjaGFydChzaF9saW5oYXMsICJsaW5lIiwgaGNhZXMoeCA9ICJBbm8iLCB5ID0gIlZhbG9yIiwgZ3JvdXAgPSAiRnVuY2FvIiksDQogICAgICAgbGVnZW5kID0gbGlzdCgNCiAgICAgICAgIHN0eWxlID0gbGlzdCgNCiAgICAgICAgICAgZm9udFdlaWdodCA9ICdwbGFpbicpKQ0KICAgICAgICAgKQ0KDQpoY2hhcnQoc2hfbGluaGFzLCAibGluZSIsIGhjYWVzKHggPSAiQW5vIiwgeSA9ICJWYWxvciIsIGdyb3VwID0gIkZ1bmNhbyIpKSAlPiUNCiAgaGNfbGVnZW5kKHN0eWxlID0gbGlzdChmb250V2VpZ2h0ID0gInBsYWluIiwgY29sb3IgPSAiIzQ1ODkzOSIpKSAlPiUNCiAgaGNfeUF4aXModGl0bGUgPSBsaXN0KHRleHQgPSAiVmFsb3IgZW0gcGVyY2VudHVhbCBkbyBQSUIiKSkgJT4lDQogIGhjX3Rvb2x0aXAoc2hhcmVkID0gIlRSVUUiKQ0KDQojIGNvbSBkeWdyYXBocw0KDQojIGNvbnZlcnRlciBhbm8gZW0gZGF0YSwgZSBvIGRhdGFmcmFtZSBlbSB0aW1lIHNlcmllcw0KDQpsaWJyYXJ5KHh0cykNCmxpYnJhcnkoZHlncmFwaHMpDQoNCnNoX3h0cyA8LSBzaF9saW5oYXMNCnNoX3h0cyRBbm8gPC0gYXMuRGF0ZShwYXN0ZShzaF94dHMkQW5vLCAxMiwgMzEsIHNlcCA9ICItIikpDQoNCnNoX3h0c1syOjRdIDwtIE5VTEwgDQpzaF94dHMkRnVuY2FvIDwtIGFzLmZhY3RvcihzaF94dHMkRnVuY2FvKQ0Kc2hfeHRzIDwtIHNoX3h0cyAlPiUNCiAgc3ByZWFkKGtleSA9ICJGdW5jYW8iLCB2YWx1ZSA9ICJWYWxvciIpDQpzaF94dHMgPC0geHRzKHNoX3h0c1ssLTFdLCBvcmRlci5ieSA9IHNoX3h0cyRBbm8pDQoNCmR5Z3JhcGgoc2hfeHRzKSAlPiUNCiAgZHlIaWdobGlnaHQoaGlnaGxpZ2h0Q2lyY2xlU2l6ZSA9IDUsIA0KICAgICAgICAgICAgICBoaWdobGlnaHRTZXJpZXNCYWNrZ3JvdW5kQWxwaGEgPSAwLjIsDQogICAgICAgICAgICAgIGhpZ2hsaWdodFNlcmllc09wdHMgPSBsaXN0KHN0cm9rZVdpZHRoID0gMyksDQogICAgICAgICAgICAgIGhpZGVPbk1vdXNlT3V0ID0gRkFMU0UpICU+JQ0KICBkeUxlZ2VuZChzaG93ID0gIm9ubW91c2VvdmVyIiwgbGFiZWxzRGl2PSJsYWJlbHMiLCBsYWJlbHNTZXBhcmF0ZUxpbmVzID0gVFJVRSkNCg0KYGBgDQo8ZGl2IGlkPSJsYWJlbHMiPg0KPC9kaXY+DQoNCiMjIE9zIGF0aXZvcw0KDQpgYGB7cn0NCmxpYnJhcnkocGxvdGx5KQ0KDQojIGxlIG9zIGRhZG9zDQoNCmF0aXZvIDwtIHJlYWQuY3N2MigibGlua3MtYXRpdm8uY3N2IikNCmF0aXZvJHZhbG9yIDwtIGFzLm51bWVyaWMoZ3N1YigiWy5dIiwgIiIsIGF0aXZvJHZhbG9yKSkNCg0KcGFzc2l2byA8LSByZWFkLmNzdjIoImxpbmtzLXBhc3Npdm8uY3N2IikNCnBhc3Npdm8kdmFsb3IgPC0gYXMubnVtZXJpYyhnc3ViKCJbLl0iLCAiIiwgcGFzc2l2byR2YWxvcikpDQoNCiMgY29yZXMNCg0KbXR4X3RyZXNfY29yZXMgPC0gY29sMnJnYih0cmVzX2NvcmVzX3Bhc3RlaXMpDQoNCmNvcmVzIDwtIE5VTEwNCmZvciAoaSBpbiAxOmRpbShtdHhfdHJlc19jb3JlcylbMl0gKSB7DQogIGNvcmVzIDwtIGMoY29yZXMsIHBhc3RlKCJyZ2JhKCIsIG10eF90cmVzX2NvcmVzWzEsaV0sIiwgIiwgIG10eF90cmVzX2NvcmVzWzIsaV0sIiwgIiwgIG10eF90cmVzX2NvcmVzWzMsaV0sIiwgMC43KSIsIHNlcCA9ICIiKSkNCn0NCg0KdGJsX2NvcmVzIDwtIGRhdGEuZnJhbWUoImVudGUiID0gbGV2ZWxzKGF0aXZvJGVudGUpLGNvcmVzKQ0KDQojIGZ1bmNhbyBkZSBwbG90YWdlbQ0KDQpwbG90YV9zYW5rZXkgPC0gZnVuY3Rpb24oZGFkb3MsIHJvdHVsb3MsIGNvcl9ub3Mpew0KICBwbG90X2x5KA0KICAgIHR5cGUgPSAic2Fua2V5IiwNCiAgICBvcmllbnRhdGlvbiA9ICJoIiwNCiAgICBvcGFjaXR5ID0gMC42LA0KICAgIHdpZHRoID0gODAwLA0KICAgIGhlaWdodCA9IDYwMCwNCiAgICB0ZXh0Zm9udCA9IGxpc3QoDQogICAgICBmYW1pbHkgPSAiU291cmNlIFNhbnMgUHJvIiwNCiAgICAgIGNvbG9yID0gIiM0NDQ0NDQiLA0KICAgICAgc2l6ZSA9IDEyKSwNCiAgICANCiAgICBub2RlID0gbGlzdCgNCiAgICAgIGxhYmVsID0gcm90dWxvcywNCiAgICAgIGNvbG9yID0gY29yX25vcywgIyMwMDRhOTMNCiAgICAgIHBhZCA9IDEwLA0KICAgICAgdGhpY2tuZXNzID0gMjUsDQogICAgICBsaW5lID0gbGlzdCgNCiAgICAgICAgY29sb3IgPSBjb3Jfbm9zLA0KICAgICAgICB3aWR0aCA9IDApKSwNCiAgICANCiAgICBob3ZlcmxhYmVsID0gbGlzdCgNCiAgICAgIGZvbnQgPSBsaXN0KA0KICAgICAgICBmYW1pbHkgPSAiU291cmNlIFNhbnMgUHJvIikpLA0KICAgIA0KICAgIGxpbmsgPSBsaXN0KA0KICAgICAgc291cmNlID0gZGFkb3Mkc3JjLA0KICAgICAgdGFyZ2V0ID0gZGFkb3MkdHJnLA0KICAgICAgdmFsdWUgPSAgZGFkb3MkdmFsb3IsDQogICAgICBjb2xvciA9ICBkYWRvcyRjb3JlcykpICU+JSANCiAgDQogICAgbGF5b3V0KA0KICAgICAgdGl0bGUgPSAiIiwNCiAgICAgIGZvbnQgPSBsaXN0KA0KICAgICAgICBmYW1pbHkgPSAiU291cmNlIFNhbnMgUHJvIiwNCiAgICAgICAgc2l6ZSA9IDExLA0KICAgICAgICBjb2xvciA9ICIjMDA0YTkzIikpDQp9DQoNCiMgZnVuY2FvIHBhcmEgcHJvY2Vzc2FyIG9zIGRhZG9zIGUgY2hhbWFyIGEgZnVuw6fDo28gZGUgcGxvdGFnZW0NCg0KIyMjIyMgaW5jbHVpciBhcmd1bWVudG8gbmEgZnVuw6fDo28gcGFyYSBjb3IgZG9zIG7Ds3MhDQoNCnBsb3RhX2VudGUgPC0gZnVuY3Rpb24oZW50ZV9pbiwgZGFkb3MsIGNvcl9ub3Mpew0KICANCiAgaWYgKGVudGVfaW4gPT0gIkNvbnNvbGlkYWRvIikgew0KICAgIGRhZG9zX2VudGUgPC0gZGFkb3N9DQogICAgZWxzZSB7ZGFkb19lbnRlIDwtIGRhZG9zICU+JSBmaWx0ZXIoZW50ZSA9PSBlbnRlX2luKQ0KICB9DQogIA0KICBsaXN0YV9ub3MgPC0gdW5pcXVlKGMobGV2ZWxzKGRhZG9zX2VudGUkdXApLCBsZXZlbHMoZGFkb3NfZW50ZSRkb3duKSkpDQogIG51bWVyb3Nfbm9zIDwtIDA6KGxlbmd0aChsaXN0YV9ub3MpLTEpDQogIG5vcyA8LSBkYXRhLmZyYW1lKGxpc3RhX25vcywgbnVtZXJvc19ub3MpDQogIA0KICBtYXRyaXogPC0gZGFkb3NfZW50ZSAlPiUNCiAgICBsZWZ0X2pvaW4obm9zLCBieSA9IGMoInVwIiA9ICJsaXN0YV9ub3MiKSkgJT4lDQogICAgcmVuYW1lKHNyYyA9IG51bWVyb3Nfbm9zKSAlPiUNCiAgICBsZWZ0X2pvaW4obm9zLCBieSA9IGMoImRvd24iID0gImxpc3RhX25vcyIpKSAlPiUNCiAgICByZW5hbWUodHJnID0gbnVtZXJvc19ub3MpDQogIA0KICBtYXRyaXogPC0gbWF0cml6ICU+JQ0KICAgIGxlZnRfam9pbih0YmxfY29yZXMpDQogIA0KICBwbG90YV9zYW5rZXkobWF0cml6LCBsaXN0YV9ub3MsIGNvcl9ub3MpDQogICNyZXR1cm4obWF0cml6KQ0KfQ0KDQojZGFkb3NfY29uc29saWRhZG8gPC0gZ2VyYV9kYWRvc19lbnRlKCJDb25zb2xpZGFkbyIpDQojZGFkb3NfVW5pYW8gPC0gZ2VyYV9kYWRvc19lbnRlKCJVbmnDo28iKQ0KI2RhZG9zX0VzdGFkb3MgPC0gZ2VyYV9kYWRvc19lbnRlKCJFc3RhZG9zIikNCiNkYWRvc19NdW5pY2lwaW9zIDwtIGdlcmFfZGFkb3NfZW50ZSgiTXVuaWPDrXBpb3MiKQ0KDQpwbG90YV9lbnRlKCJDb25zb2xpZGFkbyIsIGF0aXZvLCAiIzQ0NDQ0NCIpDQpwbG90YV9lbnRlKCJDb25zb2xpZGFkbyIsIHBhc3Npdm8sICIjMzMzMzMzIikNCg0KDQpgYGANCiMjIERpYWdyYW1hIENvbnNvbGlkYWRvDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KI3Bsb3RhX2VudGUoIkNvbnNvbGlkYWRvIikNCmBgYA0KDQo=